package com.nisco.dms.controller;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.common.collect.Lists;
import com.nisco.dms.entity.Department;
import com.nisco.dms.entity.Role;
import com.nisco.dms.entity.User;
import com.nisco.dms.entity.UserRole;
import com.nisco.dms.exception.ExistedException;
import com.nisco.dms.service.DepartmentService;
import com.nisco.dms.service.RoleService;
import com.nisco.dms.service.UserRoleService;
import com.nisco.dms.service.UserService;
import com.nisco.dms.util.ControllerUtil;
import com.nisco.dms.util.DateTools;
import com.nisco.dms.util.dwz.AjaxObject;
import com.nisco.dms.util.dwz.Page;

@Controller
@RequestMapping(value = "/user")
public class UserController {
	@Autowired
	private UserService userService;

	@Autowired
	UserRoleService userRoleService;

	@Autowired
	private RoleService roleService;

	@Autowired
	private DepartmentService deptService;

	private static final String CREATE = "user/userCreate";
	private static final String UPDATE = "user/userUpdate";
	private static final String LIST = "user/userList";
	private static final String LOOK_UP_ROLE = "user/userAssignRole";
	private static final String LOOK_USER_ROLE = "user/userDeleteRole";
	private static final String LOOK_ORG = "user/lookup2Org";
	private static String  moduleListNavId = "";
	
	@RequiresPermissions("User:save")
	// 通过注解进行权限检查
	@RequestMapping(value = "/create", method = RequestMethod.GET)
	public String preCreate() {
		return CREATE;
	}

	@RequiresPermissions("User:save")
	@RequestMapping(value = "/create", method = RequestMethod.POST)
	public @ResponseBody
	String create(User user) {
//		Subject subject = SecurityUtils.getSubject();
//		ShiroDbRealm.ShiroUser shiroUser = (ShiroDbRealm.ShiroUser) subject.getPrincipal();
		//设置创建者
		user.setCreateUser(ControllerUtil.currentUser());
		//设置创建日期
		user.setCreateDateTime(DateTools.getFullNowDateTime("yyyy-MM-dd HH:mm:ss"));
		try {
			userService.save(user);
		} catch (ExistedException e) {
			AjaxObject ajaxObject = new AjaxObject(e.getMessage());
			ajaxObject.setCallbackType("");
			ajaxObject.setStatusCode(AjaxObject.STATUS_CODE_FAILURE);
			return ajaxObject.toString();
		}
		
		AjaxObject ajaxObject = new AjaxObject("用户添加成功！");
		ajaxObject.setNavTabId(moduleListNavId);
		return ajaxObject.toString();
	}

	/**
	 * 注意：被@ModelAttribute注释的方法会在此controller每个方法执行前被执行，因此对于一个controller映射多个URL的用法来说，要谨慎使用。容易出现脏读现象。
	 * 例子： 如果在public @ResponseBody String update(User user) 中使用@ModelAttribute ,
	 *    如public @ResponseBody String update(@ModelAttribute("preloadUser") User user)。
	 *    则会在修改为完成的情况下同时进行查询，结果造成脏读现象导致修改不成功，提示报错信息如下：
	 *    "org.springframework.orm.hibernate3.HibernateSystemException: identifier of an instance of"
	 * @param id
	 * @return
	 * @author Robin 2013-4-19 下午3:57:21
	 */
	@ModelAttribute("preloadUser")
	public User getOne(@RequestParam(value = "id", required = false) String id) {
		if (id != null) {
			return userService.findById(id);
		}
		return null;
	}

	@RequiresPermissions("User:edit")
	@RequestMapping(value = "/update/{id}", method = RequestMethod.GET)
	public String preUpdate(@PathVariable String id, Map<String, Object> map) {
		User user = userService.findById(id);

		map.put("user", user);
		return UPDATE;
	}

	@RequiresPermissions("User:edit")
	@RequestMapping(value = "/update", method = RequestMethod.POST)
	public @ResponseBody
	String update(User user) {
		
		user.setStrSalt(userService.findById(user.getId()).getStrSalt());
		user.setStrPassword((userService.findById(user.getId()).getStrPassword()));
		userService.update(user);

		AjaxObject ajaxObject = new AjaxObject("用户修改成功！");
		ajaxObject.setNavTabId(moduleListNavId);
		return ajaxObject.toString();
	}

	@RequiresPermissions("User:delete")
	@RequestMapping(value = "/delete/{id}", method = RequestMethod.POST)
	public @ResponseBody
	String delete(@PathVariable String id) {
		AjaxObject ajaxObject = new AjaxObject("用户删除成功！");
		try {
			userService.delete(id);
		} catch (ExistedException e) {
			ajaxObject.setMessage(e.getMessage());
		}

		// AjaxObject ajaxObject = new AjaxObject("用户删除成功");
		ajaxObject.setCallbackType("");
		return ajaxObject.toString();
	}

	@RequiresPermissions("User:edit")
	@RequestMapping(value = "/reset/{type}/{userId}", method = RequestMethod.POST)
	public @ResponseBody
	String reset(@PathVariable String type, @PathVariable String userId) {
		User user = userService.findById(userId);
		AjaxObject ajaxObject = new AjaxObject();
		if (type.equals("password")) {
			user.setPlainPassword("123456");

			ajaxObject.setMessage("重置密码成功，默认密码为123456！");
		} else if (type.equals("status")) {
			if (user.getStrStatus().equals("enabled")) {
				user.setStrStatus("disabled");
			} else {
				user.setStrStatus("enabled");
			}

			ajaxObject.setMessage("更新状态为" + user.getStrStatus());
		}

		userService.update(user);
		ajaxObject.setCallbackType("");
		return ajaxObject.toString();
	}

	@RequiresPermissions("User:save")
	@RequestMapping(value = "/create/userRole", method = { RequestMethod.POST })
	public @ResponseBody
	void assignRole(UserRole userRole) {
		userRoleService.save(userRole);
	}

	@RequiresPermissions("User:edit")
	@RequestMapping(value = "/lookup2create/userRole/{userId}", method = { RequestMethod.GET, RequestMethod.POST })
	public String listUnassignRole(Map<String, Object> map, @PathVariable String userId) {
		Page page = new Page();
		page.setNumPerPage(Integer.MAX_VALUE);

		List<UserRole> userRoles = userRoleService.find(userId);
		List<Role> roles = roleService.findAll(page);

		List<Role> hasList = Lists.newArrayList();
		List<Role> allRoles = Lists.newArrayList(roles);
		// 删除已分配roles
		for (UserRole ur : userRoles) {
			for (Role role : roles) {
				if (ur.getRole().getId().equals(role.getId())) {
					hasList.add(role);
					break;
				}
			}
		}

		allRoles.removeAll(hasList);

		map.put("userRoles", userRoles);
		map.put("roles", allRoles);

		map.put("userId", userId);
		return LOOK_UP_ROLE;
	}

	@RequiresPermissions("User:edit")
	@RequestMapping(value = "/lookup2delete/userRole/{userId}", method = { RequestMethod.GET, RequestMethod.POST })
	public String listUserRole(Map<String, Object> map, @PathVariable String userId) {
		List<UserRole> userRoles = userRoleService.find(userId);
		map.put("userRoles", userRoles);
		return LOOK_USER_ROLE;
	}

	@RequiresPermissions("User:edit")
	@RequestMapping(value = "/delete/userRole/{userRoleId}", method = { RequestMethod.POST })
	public @ResponseBody
	void deleteUserRole(@PathVariable String userRoleId) {
		userRoleService.delete(userRoleId);
	}

	@RequiresPermissions(value = { "User:edit", "User:save" })
	@RequestMapping(value = "/lookup2org", method = { RequestMethod.GET })
	public String lookup(Map<String, Object> map) {
		Department dept = deptService.getTree();
		map.put("dept", dept);
		return LOOK_ORG;
	}

	@RequiresPermissions("User:view")
	@RequestMapping(value = "/list", method = { RequestMethod.GET, RequestMethod.POST })
	public String list(Page page, String keywords, Map<String, Object> map,HttpServletRequest request) {
		moduleListNavId = ControllerUtil.navId(moduleListNavId, (String)request.getParameter("moduleListNavId"));
		List<User> users;
		if (StringUtils.isNotBlank(keywords)) {
			users = userService.find(page, keywords);
		} else {
//			users = userService.findAll(page);
			users = userService.findByCompanyAndIsActivite(page, ControllerUtil.currentCompany().getId(), 1);
		}

		map.put("page", page);
		map.put("users", users);
		map.put("keywords", keywords);
		return LIST;
	}

}
